package com.sychip.fhc.app.data.source.local

import android.content.Context
import androidx.room.Room
import com.sychip.fhc.app.data.repo.BleDeviceRepo
import com.sychip.fhc.app.data.repo.TaskRepo
import com.sychip.fhc.app.data.repo.WsnDeviceRepo
import com.sychip.fhc.app.data.repo.WsnDeviceRssiRepo
import com.sychip.fhc.app.data.repo.WsnRssiHisRepo
import com.sychip.fhc.app.data.repo.WsnTestRecordRepo
import com.sychip.fhc.app.data.repo.impl.BleDeviceRepoImpl
import com.sychip.fhc.app.data.repo.impl.TaskRepoImpl
import com.sychip.fhc.app.data.repo.impl.WsnDeviceRepoImpl
import com.sychip.fhc.app.data.repo.impl.WsnDeviceRssiRepoImpl
import com.sychip.fhc.app.data.repo.impl.WsnRssiHisRepoImpl
import com.sychip.fhc.app.data.repo.impl.WsnTestRecordRepoImpl
import com.sychip.fhc.app.data.source.dao.BleDeviceDao
import com.sychip.fhc.app.data.source.dao.TaskDao
import com.sychip.fhc.app.data.source.dao.WsnDeviceDao
import com.sychip.fhc.app.data.source.dao.WsnDeviceRssiDao
import com.sychip.fhc.app.data.source.dao.WsnRssiHisDao
import com.sychip.fhc.app.data.source.dao.WsnTestRecordDao
import com.sychip.fhc.app.data.source.network.NetworkDataSource
import com.sychip.fhc.app.data.source.network.TaskNetworkDataSource
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {

    @Singleton
    @Binds
    abstract fun bindTaskRepository(repository: TaskRepoImpl): TaskRepo


    @Singleton
    @Binds
    abstract fun bindBleDeviceRepo(repository: BleDeviceRepoImpl):  BleDeviceRepo

    @Singleton
    @Binds
    abstract fun bindWsnDeviceRepo(repository: WsnDeviceRepoImpl):  WsnDeviceRepo

    @Singleton
    @Binds
    abstract fun bindWsnDeviceRssiRepo(repository: WsnDeviceRssiRepoImpl):  WsnDeviceRssiRepo

    @Singleton
    @Binds
    abstract fun bindWsnTestRecordRepo(repository: WsnTestRecordRepoImpl): WsnTestRecordRepo

    @Singleton
    @Binds
    abstract fun bindWsnRssiHisRepo(repository: WsnRssiHisRepoImpl): WsnRssiHisRepo
}



@Module
@InstallIn(SingletonComponent::class)
abstract class DataSourceModule {

    @Singleton
    @Binds
    abstract fun bindNetworkDataSource(dataSource: TaskNetworkDataSource): NetworkDataSource
}

@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {

    @Singleton
    @Provides
    fun provideDataBase(@ApplicationContext context: Context): ToDoDatabase {
        return Room.databaseBuilder( context.applicationContext, ToDoDatabase::class.java, "todo.db")
                        .addMigrations(MIGRATION_1_2)
                        .addMigrations(MIGRATION_2_3)
            .addMigrations(MIGRATION_3_4)
            .addMigrations(MIGRATION_4_5)
            .fallbackToDestructiveMigration(false) // 防止没有匹配到的迁移时崩溃
            .allowMainThreadQueries() // Room 原则上不允许在主线程操作数据库
            // 如果要在主线程操作数据库需要调用该函数
            .build()
    }

    @Provides
    fun provideTaskDao(database: ToDoDatabase): TaskDao = database.taskDao()

    @Provides
    fun provideBleDeviceDao(database: ToDoDatabase): BleDeviceDao = database.bleDeviceDao()

    @Provides
    fun provideWsnDeviceDao(database: ToDoDatabase): WsnDeviceDao = database.wsnDeviceDao()

    @Provides
    fun provideWsnDeviceRssiDao(database: ToDoDatabase): WsnDeviceRssiDao = database.wsnDeviceRssiDao()

    @Provides
    fun provideWsnTestRecordDao(database: ToDoDatabase): WsnTestRecordDao = database.wsnTestRecordDao()

    @Provides
    fun provideWsnRssiHisRepo(database: ToDoDatabase): WsnRssiHisDao = database.wsnRssiHisDao()
}
